#pragma once

#include <string>
#include <unordered_map>
#include <functional>
#include <fstream>
#include <sstream>
#include <cstring>

namespace lurpc {


struct service_conf {
    std::string _host;
    int _port;

    service_conf() : _host(), _port(-1) { }
    service_conf(std::string _h, int _p) : _host(std::move(_h)), _port(_p) { }
};

class rpc_services {
public:
    static bool load_from_file(const char*);
    static service_conf get(uint32_t);
    static bool set(uint32_t, const service_conf&);

private:
    static std::unordered_map<uint32_t, service_conf> _services;

};

std::unordered_map<uint32_t, service_conf> rpc_services::_services;

bool rpc_services::load_from_file(const char * _filename) {
    std::ifstream fin(_filename);
    if (!fin.is_open()) {
        printf("file open error: %s, filename: %s", strerror(errno), _filename);
        return false;
    }
    std::string line;
    std::string service_name;
    service_conf svc_conf;
    uint32_t svc_id = 0;
    int cnt = 0;
    while (getline(fin, line)) {
        auto len = line.size();
        if (len == 0) continue;
        if (line[0] != '\t' && line[0] != ' ') {
            continue;
        }
        else {
            std::string attr;
            int i = 0;
            while (i < len && line[i] == '\t' || line[i] == ' ') ++i;
            while (i < len && line[i] != ' ') {
                attr.push_back(line[i]);
                ++i;
            }
            std::string val;
            while (i < len && line[i] == '\t' || line[i] == ' ') ++i;
            while (i < len && line[i] != ' ') {
                val.push_back(line[i]);
                ++i;
            }
            if (attr == "Id") {
                svc_id = std::stoi(val);
            }
            else if (attr == "Host") {
                svc_conf._host = val;
            }
            else if (attr == "Port") {
                svc_conf._port = std::stoi(val);
            }
            else {
                printf("unknown attr: %s\n", attr.c_str());
                return false;
            }
            cnt++;
            if (cnt == 3) {
                _services[svc_id] = svc_conf;
                cnt = 0;
            }
        }
    }
    fin.close();
    return true;
}

service_conf rpc_services::get(uint32_t _id) {
    if (!_services.contains(_id)) {
        return { "", -1 };
    }
    else {
        return _services[_id];
    }
}

bool rpc_services::set(uint32_t _id, const service_conf & _svc) {
    if (_services.contains(_id)) return false;
    _services[_id] = _svc;
    return true;
}


}